﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using Kaiser.Attributes;

namespace Kaiser.Utils
{
    public class CusEnum
    {
        public string Key { get; set; }
        public int Value { get; set; }
        public string Description { get; set; }
    }

    public class EnumHelper
    {
        public static List<KeyValuePair<T, string>> GetValueAndDescriptions<T>() where T : struct
        {
            return typeof(T).GetFields()
                .Where(item => item.IsStatic)
                .ToDictionary(item => (T)Enum.Parse(typeof(T), item.Name),
                              item => ((DescriptionAttribute)item.GetCustomAttributes(typeof(DescriptionAttribute), false)[0]).Description)
                .ToList();
        }

        public static List<CusEnum> GetValueAndDescriptions(Type eEnum)
        {

            return eEnum.GetFields()
                               .Where(item => item.IsStatic).Select(x =>

                                   new CusEnum()
                                   {
                                       Description = GetFieldDescription(x),
                                       Key = x.Name,
                                       Value = x.GetValue(x).GetHashCode()
                                   }
                                   ).ToList();

        }

        protected static string GetFieldDescription(FieldInfo fieldInfo)
        {
            var attrs = fieldInfo.GetCustomAttributes(typeof(DescriptionEnumAttribute), false);
            if (attrs.Length > 0)
            {
                var descriptionEnumAttribute = attrs[0] as DescriptionEnumAttribute;
                if (descriptionEnumAttribute != null)
                    return descriptionEnumAttribute.Description;
            }
            else
            {
                var attrs2 = fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
                if (attrs2.Length > 0)
                {
                    var descriptionAttribute = attrs2[0] as DescriptionAttribute;
                    if (descriptionAttribute != null)
                        return descriptionAttribute.Description;
                }

            }
            return string.Empty;
        }


        public static List<KeyValuePair<int, string>> GetValueAndDescriptionsInt<T>() where T : struct
        {
            return typeof(T).GetFields()
                .Where(item => item.IsStatic)
                .ToDictionary(item => (int)Enum.Parse(typeof(T), item.Name),
                              item => ((DescriptionAttribute)item.GetCustomAttributes(typeof(DescriptionAttribute), false)[0]).Description)
                .ToList();
        }

        public static List<KeyValuePair<long, string>> GetValueAndDescriptionsLong(Type type) 
        {
            return type.GetFields()
                .Where(item => item.IsStatic)
                .ToDictionary(item => (long)(int)Enum.Parse(type, item.Name),
                              item => ((DescriptionAttribute)item.GetCustomAttributes(typeof(DescriptionAttribute), false)[0]).Description)
                .ToList();
        }

        public static List<string> GetDescriptions<T>() where T : struct
        {
            return typeof(T).GetFields()
                .Where(item => item.IsStatic)
                .Select(item => ((DescriptionAttribute)item.GetCustomAttributes(typeof(DescriptionAttribute), false)[0]).Description)
                .ToList();
        }

        public static List<T> GetValues<T>() where T : struct
        {
            return typeof(T).GetFields()
                .Where(item => item.IsStatic)
                .Select(item => (T)Enum.Parse(typeof(T), item.Name))
                .ToList();
        }

        public static string GetDescription<T>(T value) where T : struct
        {

            return typeof(T).GetFields()
                .Where(item => item.IsStatic)
                .Where(item =>
                    item.Name == value.ToString()
                    )
                .Select(GetFieldDescription)
                .FirstOrDefault();
        }


        public static string GetDescription<T>(int value) where T : struct
        {
            return typeof(T).GetFields()
                .Where(item => item.IsStatic)
                .Where(item =>
                    item.GetValue(null).GetHashCode() == value
                    )
                .Select(item => ((DescriptionAttribute)item.GetCustomAttributes(typeof(DescriptionAttribute), false)[0]).Description)
                .FirstOrDefault();
        }

        public static T GetValue<T>(string description) where T : struct
        {
            return typeof(T).GetFields()
                .Where(item => item.IsStatic)
                .Where(item => description == ((DescriptionAttribute)item.GetCustomAttributes(typeof(DescriptionAttribute), false)[0]).Description)
                .Select(item => (T)Enum.Parse(typeof(T), item.Name))
                .FirstOrDefault();
        }

        public static string GetDescriptionByInt<T>(int? value) where T : struct
        {
            var d = typeof(T).GetFields()
                              .Where(item => item.IsStatic)
                              .Where(item => (int)Enum.Parse(typeof(T), item.Name) == value)
                              .Select(
                                  item =>
                                  ((DescriptionAttribute)
                                   item.GetCustomAttributes(typeof(DescriptionAttribute), false)[0]).Description)
                              .FirstOrDefault();
            return d;
        }

        public static string GetDescriptionByInt(Type t, int? value)
        {
            return t.GetFields()
                .Where(item => item.IsStatic)
                .Where(item => (int)Enum.Parse(t, item.Name) == value)
                .Select(item => ((DescriptionAttribute)item.GetCustomAttributes(typeof(DescriptionAttribute), false)[0]).Description)
                .FirstOrDefault();
        }
    }
}
